/**
 * Copyright (c) 2016 Lenovo Group
 * All Rights Reserved.
 * 
 * Project Name:itsm-gateway
 * Create Time: 2016年2月19日 上午16:09:33
 */
package com.lenovo.lmrp.base.map;

import java.util.Map;

import com.lenovo.lmrp.base.ParamNameDef;
import com.lenovo.lmrp.base.map.Address.Location;
import com.lenovo.sdc.framework.net.HttpRequest;
import com.lenovo.sdc.framework.net.HttpResponse;
import com.lenovo.sdc.framework.net.HttpSession;
import com.lenovo.sdc.framework.util.AttributeBean;
import com.lenovo.sdc.framework.util.CommonUtil;
import com.lenovo.sdc.framework.util.JSONHelper;
import com.lenovo.sdc.framework.util.exception.ErrorCode;
import com.lenovo.sdc.framework.util.exception.TraceableException;

/**
 * @author zhangzhenga
 *
 */
public class BaiduMap {

    private AttributeBean params;

    public BaiduMap(AttributeBean params) {
        this.params = params;
    }

    private static final double EARTH_RADIUS = 6378.137; //地球半径

    public static class BaiduResponse {
        private Integer status;
        private Object result;
        private String message;

        public Integer getStatus() {
            return status;
        }

        public void setStatus(Integer status) {
            this.status = status;
        }

        public Object getResult() {
            return result;
        }

        public void setResult(Object result) {
            this.result = result;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        //成功返回true
        public boolean success() {
            return status == 0;
        }

    }

    private double rad(double d) {
        return d * Math.PI / 180.0; //计算弧长
    }

    /**
     * 获取两点距离
     * @param long1 经度
     * @param lat1  纬度
     * @param long2
     * @param lat2
     * @return
     */
    public double getShortestDistance(double long1, double lat1, double long2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(long1) - rad(long2);
        double s = 2 * Math.asin(Math
            .sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        // s = s * 1000;      //换算成米
        return s; //得到千米数
    }

    public double getShortestDistance(Location l1, Location l2) {
        return getShortestDistance(l1.getLng(), l1.getLat(), l2.getLng(), l2.getLat());
    }

    /**
     * 根据详细地址返回经纬度
     * @param address
     * @return
     */
    @SuppressWarnings("unchecked")
    public Address getLongLatFromAddress(String address) {
        String target = params.getAttribute("baidu.map.geocoding", "http://api.map.baidu.com/geocoder/v2/");
        Address ad = null;
        HttpRequest request = new HttpRequest(target);
        request.addParam("address", address.replaceAll(" ", ""));
        request.addParam("output", "json");
        request.addParam("ak", params.getAttribute("baidu.map.ak", ""));

        String proxyHost = params.getAttribute(ParamNameDef.HTTP_PROXY_HOST, "");
        String proxyPort = params.getAttribute(ParamNameDef.HTTP_PROXY_PORT, "");
        HttpSession sess = null;
        if (CommonUtil.isNullOrEmpty(proxyHost)) {
            sess = new HttpSession();
        }
        else {
            sess = new HttpSession(proxyHost + ":" + proxyPort);
        }
        HttpResponse response;
        try {
            response = sess.sendGetRequest(request);
            if (response.getStatus() == 200) {
                BaiduResponse bdResponse = JSONHelper.fromJSON(response.getBody(), BaiduResponse.class);
                if (bdResponse.success()) {
                    Map<String, Object> result = (Map<String, Object>) bdResponse.getResult();
                    Map<String, Object> location = (Map<String, Object>) result.get("location");
                    ad = new Address();
                    ad.setAddress(address);
                    ad.setLocation(new Location(location.get("lng").toString(), location.get("lat").toString()));
                    ad.setPrecise(Integer.parseInt(result.get("precise").toString()));
                    ad.setConfidence(Integer.parseInt(result.get("confidence").toString()));
                    ad.setLevel(result.get("level").toString());
                    return ad;
                }
                else {
                    throw new TraceableException(ErrorCode.NET_READ_ERROR, target);
                }
            }
            else {
                throw new TraceableException(ErrorCode.NET_READ_ERROR, target);
            }
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.NET_READ_ERROR, exp);
        }
    }
}
